package com.hyjx.framework.component.fastdfs;

import com.hyjx.framework.common.PropertyUtil;
import org.apache.commons.io.IOUtils;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.FileInfo;
import org.csource.fastdfs.ServerInfo;
import org.csource.fastdfs.StorageClient;
import org.csource.fastdfs.StorageServer;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * 分步式文件存储的管理类
 */
public class FileManager implements FileManagerConfig {
    private static final long serialVersionUID = -8099544552104824881L;

    private static Logger logger = LoggerFactory.getLogger(FileManager.class);

    private TrackerClient trackerClient;
    private TrackerServer trackerServer;
    private StorageServer storageServer;
    private StorageClient storageClient;

    { // Initialize Fast DFS Client configurations
        try {
            ClassLoader classloader = Thread.currentThread().getContextClassLoader();
            String classPath = new File(FileManager.class.getResource("/").getFile()).getCanonicalPath();
            //String fdfsClientConfigFilePath = classPath + File.separator + CLIENT_CONFIG_FILE;
            String fdfsClientConfigFilePath = this.creatTmpFile();
            logger.info("Fast DFS configuration file path:" + fdfsClientConfigFilePath);
            ClientGlobal.init(fdfsClientConfigFilePath);
            trackerClient = new TrackerClient();
            trackerServer = trackerClient.getConnection();
            storageClient = new StorageClient(trackerServer, storageServer);
        } catch (Exception e) {
            logger.error("FileManager init failed", e);
        }
    }

    public String upload(FastDFSFile file) {
        logger.info("File Name: " + file.getName() + "     File Length: " + file.getContent().length);

        NameValuePair[] meta_list = new NameValuePair[3];
        meta_list[0] = new NameValuePair("width", "120");
        meta_list[1] = new NameValuePair("heigth", "120");
        meta_list[2] = new NameValuePair("author", "Diandi");

        long startTime = System.currentTimeMillis();
        String[] uploadResults = null;
        try {
            uploadResults = storageClient.upload_file(file.getContent(), file.getExt(), meta_list);
        } catch (IOException e) {
            logger.error("IO Exception when uploadind the file: " + file.getName(), e);
        } catch (Exception e) {
            logger.error("Non IO Exception when uploadind the file: " + file.getName(), e);
        }
        logger.info("upload_file time used: " + (System.currentTimeMillis() - startTime) + " ms");

        if (uploadResults == null) {
            logger.error("upload file fail, error code: " + storageClient.getErrorCode());
        }

        String groupName = uploadResults[0];
        String remoteFileName = uploadResults[1];

        String fileAbsolutePath = PROTOCOL + trackerServer.getInetSocketAddress().getHostName() + SEPARATOR
                + ClientGlobal.g_tracker_http_port + SEPARATOR + groupName + SEPARATOR + remoteFileName;

        logger.info("upload file successfully!!!  " + "group_name: " + groupName + ", remoteFileName:" + " "
                + remoteFileName);

        return fileAbsolutePath;

    }

    public FileInfo getFile(String groupName, String remoteFileName) {
        try {
            return storageClient.get_file_info(groupName, remoteFileName);
        } catch (IOException e) {
            logger.error("IO Exception: Get File from Fast DFS failed", e);
        } catch (Exception e) {
            logger.error("Non IO Exception: Get File from Fast DFS failed", e);
        }
        return null;
    }

    public void deleteFile(String groupName, String remoteFileName) throws Exception {
        storageClient.delete_file(groupName, remoteFileName);
    }

    public void downloadFile(String remoteFileName, String destPath) {
        try {
            String fileName = remoteFileName.substring(remoteFileName.lastIndexOf("/") + 1);
            byte[] b = storageClient.download_file("group1", remoteFileName);
            IOUtils.write(b, new FileOutputStream(destPath + File.separator + fileName));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public byte[] download(String groupName, String remoteFileName) {
        try {
            return storageClient.download_file(groupName, remoteFileName);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return new byte[0];
    }

    public StorageServer[] getStoreStorages(String groupName) throws IOException {
        return trackerClient.getStoreStorages(trackerServer, groupName);
    }

    public ServerInfo[] getFetchStorages(String groupName, String remoteFileName) throws IOException {
        return trackerClient.getFetchStorages(trackerServer, groupName, remoteFileName);
    }


    public String creatTmpFile() {
        try {
            InputStream is = (InputStream) PropertyUtil.class.getResourceAsStream("/config/global.properties");
            File file = new File("tmp.properties");
            if (file.exists()) {
                file.delete();
            }
            file.createNewFile();
            FileOutputStream out = new FileOutputStream(file);
            byte b[] = new byte[1024];
            while (is.read(b) != -1) {
                out.write(b);
            }
            return file.getAbsolutePath();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
